import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JOptionPane;

public class ChatClient implements Observer {
	private static final String IP = "127.0.0.1";
	private static final int PORT = 5555;
	private UserSenderConnection sender;
	private UserReceiverConnection receiver;
	private Socket socket;
	private ClientFrame frame;
	private String nickname;
	private boolean connectionLost;

	public ChatClient() {

		try {
			connectionLost = false;

			initConnection();

			do {
				nickname = JOptionPane.showInputDialog(null,
						"Inserisci nickname: ", "Nickname",
						JOptionPane.INFORMATION_MESSAGE);
			} while (nickname.equals(""));

			EventQueue.invokeLater(new Runnable() {
				public void run() {
					try {
						frame = new ClientFrame(nickname);
						frame.setVisible(true);
						frame.setSendListener(new SendMessageListener());
						
						sender.addMessageToSend(new Message(nickname, "",
								OperationType.OPEN));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});

			// GESTORE DELLA CHIUSURA DELL'APPLICAZIONE
			Runtime.getRuntime().addShutdownHook(new Thread() {
				@Override
				public void run() {

					sender.addMessageToSend(new Message(nickname, "",
							OperationType.CLOSE));

					destroyConnection();
					System.out.println("Chiusura connessione");
				}
			});
		} catch (IOException e) {
			System.out.println("Impossibile connettersi al server");
		}

	}

	private void initConnection() throws UnknownHostException, IOException {
		socket = new Socket(InetAddress.getByName(IP), PORT);

		sender = new UserSenderConnection(socket);
		sender.start();

		receiver = new UserReceiverConnection(socket);
		receiver.addObserver(this);
		Thread receiverThread = new Thread(receiver);
		receiverThread.start();
	}

	private void destroyConnection() {

		try {
			if (sender != null)
				sender.setStopped();
			if (receiver != null)
				receiver.setStopped();
			if (socket != null)
				socket.close();
		} catch (IOException e) {
		}

	}

	public static void main(String args[]) {
		new ChatClient();

	}

	@Override
	public void update(Observable o, Object arg) {
		Message m = (Message) arg;
		if (m != null) {
			frame.addMessage(m, false);
		} else {
			connectionLost = true;
			JOptionPane.showMessageDialog(null,
					"Connessione col server interrotta",
					"Errore di connessione", JOptionPane.ERROR_MESSAGE);
		}

	}

	private class SendMessageListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			String text = frame.getMessageText();
			if (!text.equals("")) {
				// Se la connessione è caduta provo a riattivarla
				if (connectionLost) {
					try {
						initConnection();
						sender.addMessageToSend(new Message(nickname, "",
								OperationType.OPEN));
						connectionLost = false;
					} catch (IOException e1) {
						JOptionPane.showMessageDialog(null,
								"Server non raggiungibile",
								"Errore di connessione",
								JOptionPane.ERROR_MESSAGE);
					}

				}
				// Se la connessione è attiva o sono riuscito a riattivarla
				// invio il messaggio
				if (!connectionLost) {
					frame.addMessage(new Message(nickname, text,
							OperationType.MESSAGE), true);
					Message m = new Message(nickname, text,
							OperationType.MESSAGE);
					sender.addMessageToSend(m);
				}
			}
		}

	}
}
